/**
  ******************************************************************************
  * @file           
  * @author         古么宁
  * @brief          
  ******************************************************************************
  *
  * COPYRIGHT(c) 2019 GoodMorning
  *
  ******************************************************************************
  */
/* Includes ---------------------------------------------------*/
#include <stdint.h>
#include "iec10x.h"
#include "devif.h"// devif.h

/* Private types ------------------------------------------------------------*/

/* Private macro ------------------------------------------------------------*/

/* Private function prototypes -----------------------------------------------*/

//------------------------------------------------------------------------------

#include "SIQ.h"
#include "DIQ.h"
#include "NVA.h"
#include "STD.h"
#include "SVA.h"
#include "VTI.h"
#include "BSI.h"
#include "OCI.h"
#include "SEP.h"
#include "SPE.h"
#include "BCR.h"
#include "SCD.h"
//#include "QCC.h"

const unsigned char iec_tysize[128] = {
	0,
	sizeof(SIQ0T_t),
	sizeof(SIQ24T_t),
	sizeof(DIQ0T_t),
	sizeof(DIQ24T_t),
	sizeof(VTI0T_t),
	sizeof(VTI24T_t),
	sizeof(BSI0T_t),
	sizeof(BSI24T_t),
	sizeof(NVA0T_t),
	sizeof(NVA24T_t),//10
	sizeof(NVA0T_t),
	sizeof(NVA24T_t),
	sizeof(STD0T_t),
	sizeof(STD24T_t),
	sizeof(BCR0T_t),
	sizeof(BCR24T_t),
	sizeof(SEP24T_t),
	sizeof(SPE24T_t),
	sizeof(OCI24T_t),
	sizeof(SCD_t),//20
	sizeof(NVA_t),
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	sizeof(SIQ56T_t),//30
	sizeof(DIQ56T_t),
	sizeof(VTI56T_t),
	sizeof(BSI56T_t),
	sizeof(NVA56T_t),
	sizeof(NVA56T_t),
	sizeof(STD56T_t),
	sizeof(BCR56T_t),
	sizeof(SEP56T_t),
	sizeof(SPE56T_t),
	sizeof(OCI56T_t),//40
	0,
	0,
	0,
	0,
	sizeof(SIQ0T_t),
	sizeof(DIQ0T_t),
	0,
	sizeof(NVAset_t),
	sizeof(SVAset_t),
	sizeof(STDset_t),//50
	4,
	0,
	0,
	0,
	0,
	0,
	0,
	sizeof(SIQ56T_t),
	sizeof(DIQ56T_t),
	0,//60
	sizeof(NVAset_t) + sizeof(CP56Time2a_t),
	sizeof(SVAset_t) + sizeof(CP56Time2a_t),
	sizeof(STDset_t) + sizeof(CP56Time2a_t),
	sizeof(BSI56T_t),
	0,
	0,
	0,
	0,
	0,
	1,//70
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,//80
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,//90
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	sizeof(char),//100
	1,
	0,
	sizeof(CP56Time2a_t),
	4,
	1,
	sizeof(CP56Time2a_t),
	0,
	0,
	0,
	0,//110
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0,//120
};



/**
  * @brief    接口管理插入升序链表
  * @param    root     设备管理根目录，一般为 bus->device 
  * @param    newdev   新设备接口管理模块
  * @return   成功返回 0
*/
static int iec_devif_insert(struct iec_slist * root , struct iec_devif * newdev)
{
	struct iec_slist ** node = &root->next ;
	while(*node) {
		struct iec_devif * dev = container_of(*node, struct iec_devif, node);
		if ( dev->type > newdev->type )
			break;
		else
		if (dev->type == newdev->type )
			return -1;
		else 
			node = &(*node)->next;
	}

	newdev->node.next = *node ;
	*node = &newdev->node;
	return 0;
}


/**
  * @brief    设备接口管理注册
  * @param    root     : 设备管理根目录，一般为 bus->device 
  * @param    type     : 当前数据接口的类型
  * @param    statfn   : 信息结构体状态获取接口
  * @param    getfn    : 信息体结构体内容获取接口
  * @param    profn    : 信息体结构体内容处理接口
  * @return   成功返回 0
*/
int iec_devif_register(
	struct iec_slist * root      ,
	unsigned char      type      ,
	dev_statfn_t       statfn    ,
	dev_getfn_t        getfn     ,
	dev_profn_t        profn   ) 
{
	struct iec_devif * newdev = iec_malloc(sizeof(struct iec_devif));
	if (NULL == newdev) {
		return -1;
	}

	newdev->type    = type                    ;
	newdev->argsize = iec_tysize[type & 0x7f] ;
	newdev->profn   = profn                   ;
	newdev->readfn  = getfn                   ;
	newdev->statefn = statfn                  ;

	if (0 != iec_devif_insert(root,newdev)) {
		iec_free(newdev);
		return -2;
	}

	return 0;
}




/**
  * @author   古么宁
  * @brief    根据 ASDU 类型查找用户设备接口
  * @param    root     : 设备管理根目录，一般为 bus->device 
  * @param    ASDUtype :  ASDU 类型
  * @note     此处的接口在 @see iec_devif_insert 注册
  * @return   设备接口结构体指针
*/
struct iec_devif * iec_devif_find(struct iec_slist * root ,unsigned char ASDUtype)
{
	struct iec_devif * search ;
	struct iec_slist * node ;
	for (node = root->next; node ; node = node->next ) {
		search = container_of(node, struct iec_devif, node);
		if (search->type > ASDUtype)
			break ;
		else
		if (search->type == ASDUtype)
			return search;
	} 
	return NULL;
}




/**
  * @brief    设备接口销毁
  * @param    root     设备管理根目录，一般为 bus->device 
  * @return   成功返回 0
*/
void iec_device_destroy(struct iec_slist * root)
{
	struct iec_devif * search ;
	struct iec_slist * node = root->next ;
	root->next = NULL;
	while(node) {
		search = container_of(node, struct iec_devif, node);
		node = node->next ;
		iec_free(search);
	}
}

